{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "0ebfe616",
   "metadata": {},
   "source": [
    "## OpenAI 메타데이터 태거\n",
    "\n",
    "문서를 수집할 때 제목, 톤 또는 문서의 길이와 같은 구조화된 메타데이터로 태그하는 것이 유용할 수 있습니다. 이를 통해 나중에 더 타겟팅된 유사성 검색을 할 수 있습니다. 그러나 대량의 문서에 대해 이러한 라벨링 과정을 수동으로 수행하는 것은 지루할 수 있습니다.\n",
    "\n",
    "`OpenAIMetadataTagger` 문서 변환기는 제공된 스키마에 따라 각 제공된 문서에서 메타데이터를 추출하여 이 과정을 자동화합니다. 이는 내부적으로 구성 가능한 `OpenAI Functions`-powered 체인을 사용하므로, 사용자 지정 LLM 인스턴스를 전달하는 경우, 이는 함수 지원이 있는 `OpenAI` 모델이어야 합니다.\n",
    "\n",
    "**참고:** 이 문서 변환기는 완전한 문서와 가장 잘 작동하므로, 다른 분할이나 처리를 하기 전에 먼저 전체 문서로 실행하는 것이 가장 좋습니다!\n",
    "\n",
    "**주요내용**\n",
    "\n",
    "- 🤖 **자동화된 메타데이터 태깅**: OpenAI를 이용해 문서에 메타데이터를 자동으로 추가하는 방법\n",
    "- 🛠️ **사용자 정의 가능**: JSON Schema와 Pydantic을 활용한 유연한 메타데이터 스키마 설정\n",
    "- 🛠️ **구성 가능한 체인**: 사용자 지정 LLM 인스턴스를 통한 태깅 프로세스\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "54a6700c",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_community.document_transformers.openai_functions import (\n",
    "    create_metadata_tagger,\n",
    ")\n",
    "from langchain_openai import ChatOpenAI"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5cf76329",
   "metadata": {},
   "source": [
    "## 데이터 로드, Document Loader\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "732e29a2",
   "metadata": {},
   "source": [
    "> 데이터 미리보기\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "d2fee6d0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Position</th>\n",
       "      <th>rating</th>\n",
       "      <th>title</th>\n",
       "      <th>review</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1</td>\n",
       "      <td>평점5</td>\n",
       "      <td>본 리뷰내용은 제가 타쇼핑몰에서 구매 후 썼던 내용을 그대로 옮긴 내용임을 먼저 밝...</td>\n",
       "      <td>본 리뷰내용은 제가 타쇼핑몰에서 구매 후 썼던 내용을 그대로 옮긴 내용임을 먼저 밝...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2</td>\n",
       "      <td>평점5</td>\n",
       "      <td>두번째 구매에요. 거실에서 사용중이었는데 방에서 사용하려고 하나 더 구매했어요.키감...</td>\n",
       "      <td>두번째 구매에요. 거실에서 사용중이었는데 방에서 사용하려고 하나 더 구매했어요.\\n...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>3</td>\n",
       "      <td>평점5</td>\n",
       "      <td>기존에 게이밍 키보드라 높이가 높아 사무용으로는 적합하지 않았는데 높이가 딱 좋습니...</td>\n",
       "      <td>기존에 게이밍 키보드라 높이가 높아 사무용으로는 적합하지 않았는데 높이가 딱 좋습니...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>4</td>\n",
       "      <td>평점4</td>\n",
       "      <td>키보드 자체는 매우 좋습니다. 키감도 확실히 부드럽고 좋아요. 디자인도 비싼만큼 이...</td>\n",
       "      <td>키보드 자체는 매우 좋습니다. 키감도 확실히 부드럽고 좋아요. 디자인도 비싼만큼 이...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>5</td>\n",
       "      <td>평점5</td>\n",
       "      <td>첫소감은 만족이에요 배송도 하루만에 받았고무게가 적당히 묵직해서 안정감있어요키 눌리...</td>\n",
       "      <td>첫소감은 만족이에요 배송도 하루만에 받았고\\n무게가 적당히 묵직해서 안정감있어요\\n...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>6</td>\n",
       "      <td>평점5</td>\n",
       "      <td>2주 정도 사용하고 쓰는 리뷰입니다.1. 배송 : 에어캡으로 한번싸서 박스 흠집없이...</td>\n",
       "      <td>2주 정도 사용하고 쓰는 리뷰입니다.\\n\\n1. 배송 : 에어캡으로 한번싸서 박스 ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>7</td>\n",
       "      <td>평점5</td>\n",
       "      <td>사무직군에 5년이상 종사중인 사람입니다로지텍 콰이어트315(키보드235 마우스330...</td>\n",
       "      <td>사무직군에 5년이상 종사중인 사람입니다\\n로지텍 콰이어트315(키보드235 마우스3...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>8</td>\n",
       "      <td>평점1</td>\n",
       "      <td>아무리 생각해도 황당해서 리뷰 남겨요이모델 키보드 검색하면 여러곳에서 나오는데 굳이...</td>\n",
       "      <td>아무리 생각해도 황당해서 리뷰 남겨요\\n이모델 키보드 검색하면 여러곳에서 나오는데 ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>9</td>\n",
       "      <td>평점5</td>\n",
       "      <td>가격때문에 정말 고민하고 고민하고 고민하다 지른 키보드입니다. 평소에 로지텍 키보드...</td>\n",
       "      <td>가격때문에 정말 고민하고 고민하고 고민하다 지른 키보드입니다. 평소에 로지텍 키보드...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>10</td>\n",
       "      <td>평점5</td>\n",
       "      <td>역시 MX Keys</td>\n",
       "      <td>사무용으로 사무실에서 사용하고 있는데 집에서 사용할려고 하나 더 추가 구매 했네요....</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   Position rating                                              title  \\\n",
       "0         1    평점5  본 리뷰내용은 제가 타쇼핑몰에서 구매 후 썼던 내용을 그대로 옮긴 내용임을 먼저 밝...   \n",
       "1         2    평점5  두번째 구매에요. 거실에서 사용중이었는데 방에서 사용하려고 하나 더 구매했어요.키감...   \n",
       "2         3    평점5  기존에 게이밍 키보드라 높이가 높아 사무용으로는 적합하지 않았는데 높이가 딱 좋습니...   \n",
       "3         4    평점4  키보드 자체는 매우 좋습니다. 키감도 확실히 부드럽고 좋아요. 디자인도 비싼만큼 이...   \n",
       "4         5    평점5  첫소감은 만족이에요 배송도 하루만에 받았고무게가 적당히 묵직해서 안정감있어요키 눌리...   \n",
       "5         6    평점5  2주 정도 사용하고 쓰는 리뷰입니다.1. 배송 : 에어캡으로 한번싸서 박스 흠집없이...   \n",
       "6         7    평점5  사무직군에 5년이상 종사중인 사람입니다로지텍 콰이어트315(키보드235 마우스330...   \n",
       "7         8    평점1  아무리 생각해도 황당해서 리뷰 남겨요이모델 키보드 검색하면 여러곳에서 나오는데 굳이...   \n",
       "8         9    평점5  가격때문에 정말 고민하고 고민하고 고민하다 지른 키보드입니다. 평소에 로지텍 키보드...   \n",
       "9        10    평점5                                         역시 MX Keys   \n",
       "\n",
       "                                              review  \n",
       "0  본 리뷰내용은 제가 타쇼핑몰에서 구매 후 썼던 내용을 그대로 옮긴 내용임을 먼저 밝...  \n",
       "1  두번째 구매에요. 거실에서 사용중이었는데 방에서 사용하려고 하나 더 구매했어요.\\n...  \n",
       "2  기존에 게이밍 키보드라 높이가 높아 사무용으로는 적합하지 않았는데 높이가 딱 좋습니...  \n",
       "3  키보드 자체는 매우 좋습니다. 키감도 확실히 부드럽고 좋아요. 디자인도 비싼만큼 이...  \n",
       "4  첫소감은 만족이에요 배송도 하루만에 받았고\\n무게가 적당히 묵직해서 안정감있어요\\n...  \n",
       "5  2주 정도 사용하고 쓰는 리뷰입니다.\\n\\n1. 배송 : 에어캡으로 한번싸서 박스 ...  \n",
       "6  사무직군에 5년이상 종사중인 사람입니다\\n로지텍 콰이어트315(키보드235 마우스3...  \n",
       "7  아무리 생각해도 황당해서 리뷰 남겨요\\n이모델 키보드 검색하면 여러곳에서 나오는데 ...  \n",
       "8  가격때문에 정말 고민하고 고민하고 고민하다 지른 키보드입니다. 평소에 로지텍 키보드...  \n",
       "9  사무용으로 사무실에서 사용하고 있는데 집에서 사용할려고 하나 더 추가 구매 했네요....  "
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import pandas as pd\n",
    "\n",
    "pd.read_csv(\"./data/keyboard-review.csv\").head(10)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c12a9d41",
   "metadata": {},
   "source": [
    "CSVLoader 로 .csv 리뷰파일로부터 데이터를 읽어서 Document 리스트 형식으로 로드하여 data 에 대입합니다\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "13a2fc3e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "총 리뷰의 개수: 20\n",
      "Position: 1\n",
      "rating: 평점5\n",
      "title: 본 리뷰내용은 제가 타쇼핑몰에서 구매 후 썼던 내용을 그대로 옮긴 내용임을 먼저 밝힙니다.--------------------------------------------------\n",
      "review: 본 리뷰내용은 제가 타쇼핑몰에서 구매 후 썼던 내용을 그대로 옮긴 내용임을 먼저 밝힙니다.\n",
      "--------------------------------------------------------------\n",
      "키보드를 이렇게 비싼 돈을 주고 살 필요가 있는가에 대해서 무척이나 고민이 많았고, 제품 관련 블로그 및 유튜브 리뷰만 수십개를 보면서 생각에 생각을 더했습본니다.\n",
      "\n",
      "이참에 아예 기계식 키보드로 넘어갈까도 했는데, 기계식 키보드는 일단 시작금액부터가 타 키보드와는 다르고, 한번 구매를 하면 이후부터는 보다 본인에게 맞는 축 종류 및 키캡 등을 찾아 계속 업글에 업글을 하는 경우가 많아서 기계식 키보드가 아닌 다른 성능좋은 키보드를 사는게 좋겠다고 판단했습니다.\n",
      "\n",
      "그래서 오랜 고민을 마치고 구매한 제품이 바로 로지텍사의 이 MX KEYS입니다.\n",
      "\n",
      "사실 로지텍사의 키보드는 나름 저도 많이 사용을 했었는데, 이제는 이 제품이 정말 마지막이라는 생각(?)으로 구입했습니다.\n",
      "\n",
      "제품은 가격(?)만큼이나 묵직한 느낌입니다. 그래서 키보드가 밀린다는 생각은 들지 않습니다. 물론 이 키보드를 들고 다른 공간에 가서 놓고 쓰는데는 지장은 없겠으나, 가급적이면 한 곳에 놓고 쓰는 것이 좋겠다는 생각입니다.\n",
      "\n",
      "아무래도 펜타그래프 타입 키보드의 끝판왕 제품이라 그런지 조용하면서 부드러운 타건감, 우수한 제품 마감 및 디자인 등 역시 비싼 몸값을 하는 제품이라는 판단입니다.\n",
      "\n",
      "이런 일반적인 특징 외에 몇가지 좋은 점을 더 적어보면\n",
      "\n",
      "1. C타입 케이블로 충전을 할 수 있는데, 이에 은근 편합니다. 저는 집에서 마음편하게 본 키보드를 쓰다 보니 백플레이트 LED도 켜놓고 계속 쓰는데, 좀 키보드를 오래 썼다 싶으면 그냥 C타입 케이블로 연결해서 충전을 하면 되니 좋더군요.\n",
      "\n",
      "2. 블루투스를 이용해서 총 3대의 기계를 연결할 수 있습니다. 디바이스별 상황에 맞게 연결되니 무척 편리합니다.\n",
      "\n",
      "3. 본 키보드는 상당히 전문적인 전용 프로그램이 지원됩니다. 이른바 로지텍옵션이라는 프로그램인데, Function키 설정, 프로그램 및 키별 맵핑, 백플레이트 LED 켜기 여부 등 세세한 변경이 가능하기 때문에 언제든지 본인 입맛에 맞게 설정이 가능합니다.\n",
      "\n",
      "4. 게임을 위해서도 사용해 보았는데, 크게 반응이 늦다는 생각이 들지는 않았습니다만.. 어떤 분들은 게임용도로는 추천치 않으시더군요. ^^;\n",
      "\n",
      "본 제품은 펜타그래프 키보드의 끝판왕이라 불릴만큼 매력을 가지고 있는 멋진 제품입니다. 다소 가격은 높은 편이나 구매 후 매우 만족하며 쓰고 있어 추천합니다.\n",
      "\n",
      "PS) 22년 1월에 본 제품이 너무 마음에 들어서 회사에서도 집과 같은 환경에서 타이핑을 하려고 네이버 쇼핑에서 한대 더 구매했습니다.\n"
     ]
    }
   ],
   "source": [
    "from langchain_community.document_loaders.csv_loader import CSVLoader\n",
    "\n",
    "# 리뷰 데이터를 불러옵니다.\n",
    "loader = CSVLoader(file_path=\"./data/keyboard-review.csv\")\n",
    "data = loader.load()\n",
    "print(f\"총 리뷰의 개수: {len(data)}\")\n",
    "print(data[0].page_content)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8b99004e",
   "metadata": {},
   "source": [
    "## create_metadata_tagger\n",
    "\n",
    "**모델**\n",
    "\n",
    "- `ChatOpenAI` 객체 `llm`은 특정 온도(`temperature=0`)와 모델(`model=\"gpt-3.5-turbo\"`)을 사용하여 초기화합니다.\n",
    "\n",
    "- [참고]: OpenAI Functions 기반으로 동작하기 때문에 **모델은 OpenAI 기반 모델이어야 합니다.**\n",
    "\n",
    "Pydantic 스키마로 문서 변환기를 초기화 합니다.\n",
    "\n",
    "**Properties 정의**\n",
    "\n",
    "- `Properties` 클래스는 리뷰에 대한 메타데이터를 정의합니다. 여기서 메타데이터에 추출하고자 하는 정보와 description을 정의합니다.\n",
    "\n",
    "- `Properties` 에는 상품 리뷰에서 추출한 키워드(`keyword`), 디자인 평가(`design`), 만족스러운 점(`satisfaction_points`), 개선사항(`improvement_areas`), 어조(`tone`), 그리고 평점(`rating`)을 포함하는 JSON 스키마를 정의합니다.\n",
    "\n",
    "- 여기서 `tone`은 `positive` 또는 `negative` 값만을 가질 수 있습니다.\n",
    "\n",
    "- _필수 필드_ 는 키워드, 만족한 부분, 개선할 사항, 평점, 어조입니다.\n",
    "\n",
    "**create_metadata_tagger**\n",
    "\n",
    "- `create_metadata_tagger` 함수를 사용하여 `Properties` 클래스를 기반으로 문서 변환기(`document_transformer`)를 생성합니다.\n",
    "- `transform_documents` 함수는 원본 데이터로부터 태깅 정보를 추출하는 함수입니다.\n",
    "- `document_transformer.transform_documents(변환데이터, prompt=프롬프트)` 함수를 사용하여 변환을 진행합니다. 변환시 prompt 키는 생략 가능합니다.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "119b8307",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Position: 1\n",
      "rating: 평점5\n",
      "title: 본 리뷰내용은 제가 타쇼핑몰에서 구매 후 썼던 내용을 그대로 옮긴 내용임을 먼저 밝힙니다.--------------------------------------------------\n",
      "review: 본 리뷰내용은 제가 타쇼핑몰에서 구매 후 썼던 내용을 그대로 옮긴 내용임을 먼저 밝힙니다.\n",
      "--------------------------------------------------------------\n",
      "키보드를 이렇게 비싼 돈을 주고 살 필요가 있는가에 대해서 무척이나 고민이 많았고, 제품 관련 블로그 및 유튜브 리뷰만 수십개를 보면서 생각에 생각을 더했습본니다.\n",
      "\n",
      "이참에 아예 기계식 키보드로 넘어갈까도 했는데, 기계식 키보드는 일단 시작금액부터가 타 키보드와는 다르고, 한번 구매를 하면 이후부터는 보다 본인에게 맞는 축 종류 및 키캡 등을 찾아 계속 업글에 업글을 하는 경우가 많아서 기계식 키보드가 아닌 다른 성능좋은 키보드를 사는게 좋겠다고 판단했습니다.\n",
      "\n",
      "그래서 오랜 고민을 마치고 구매한 제품이 바로 로지텍사의 이 MX KEYS입니다.\n",
      "\n",
      "사실 로지텍사의 키보드는 나름 저도 많이 사용을 했었는데, 이제는 이 제품이 정말 마지막이라는 생각(?)으로 구입했습니다.\n",
      "\n",
      "제품은 가격(?)만큼이나 묵직한 느낌입니다. 그래서 키보드가 밀린다는 생각은 들지 않습니다. 물론 이 키보드를 들고 다른 공간에 가서 놓고 쓰는데는 지장은 없겠으나, 가급적이면 한 곳에 놓고 쓰는 것이 좋겠다는 생각입니다.\n",
      "\n",
      "아무래도 펜타그래프 타입 키보드의 끝판왕 제품이라 그런지 조용하면서 부드러운 타건감, 우수한 제품 마감 및 디자인 등 역시 비싼 몸값을 하는 제품이라는 판단입니다.\n",
      "\n",
      "이런 일반적인 특징 외에 몇가지 좋은 점을 더 적어보면\n",
      "\n",
      "1. C타입 케이블로 충전을 할 수 있는데, 이에 은근 편합니다. 저는 집에서 마음편하게 본 키보드를 쓰다 보니 백플레이트 LED도 켜놓고 계속 쓰는데, 좀 키보드를 오래 썼다 싶으면 그냥 C타입 케이블로 연결해서 충전을 하면 되니 좋더군요.\n",
      "\n",
      "2. 블루투스를 이용해서 총 3대의 기계를 연결할 수 있습니다. 디바이스별 상황에 맞게 연결되니 무척 편리합니다.\n",
      "\n",
      "3. 본 키보드는 상당히 전문적인 전용 프로그램이 지원됩니다. 이른바 로지텍옵션이라는 프로그램인데, Function키 설정, 프로그램 및 키별 맵핑, 백플레이트 LED 켜기 여부 등 세세한 변경이 가능하기 때문에 언제든지 본인 입맛에 맞게 설정이 가능합니다.\n",
      "\n",
      "4. 게임을 위해서도 사용해 보았는데, 크게 반응이 늦다는 생각이 들지는 않았습니다만.. 어떤 분들은 게임용도로는 추천치 않으시더군요. ^^;\n",
      "\n",
      "본 제품은 펜타그래프 키보드의 끝판왕이라 불릴만큼 매력을 가지고 있는 멋진 제품입니다. 다소 가격은 높은 편이나 구매 후 매우 만족하며 쓰고 있어 추천합니다.\n",
      "\n",
      "PS) 22년 1월에 본 제품이 너무 마음에 들어서 회사에서도 집과 같은 환경에서 타이핑을 하려고 네이버 쇼핑에서 한대 더 구매했습니다.\n",
      "\n",
      "{\"keyword\": [\"로지텍사\", \"MX KEYS\", \"키보드\", \"C타입 케이블\", \"블루투스\", \"로지텍옵션\", \"프로그램\", \"게임\"], \"design\": null, \"satisfaction_points\": [\"가격\", \"묵직한 느낌\", \"조용하면서 부드러운 타건감\", \"우수한 제품 마감 및 디자인\", \"C타입 케이블로 충전 가능\", \"블루투스로 3대의 기계 연결 가능\", \"로지텍옵션 프로그램 지원\", \"매우 만족\"], \"improvement_areas\": [], \"tone\": \"positive\", \"rating\": 5, \"source\": \"./data/keyboard-review.csv\", \"row\": 0}\n",
      "\n",
      "---------------\n",
      "\n",
      "Position: 2\n",
      "rating: 평점5\n",
      "title: 두번째 구매에요. 거실에서 사용중이었는데 방에서 사용하려고 하나 더 구매했어요.키감이 진짜 좋고 소리도 타자 치면 약간 보글보글한 소리가 넘 좋아요. 통울림도 없고 사용감이 넘 조\n",
      "review: 두번째 구매에요. 거실에서 사용중이었는데 방에서 사용하려고 하나 더 구매했어요.\n",
      "키감이 진짜 좋고 소리도 타자 치면 약간 보글보글한 소리가 넘 좋아요. 통울림도 없고 사용감이 넘 조아서 편해요.\n",
      "다만 이번 온 제품은 키 인쇄가 전 제품보다 약간 흐리더라고요. 사용하는데 뭔가 낯설다 했는데 키에 인쇄가 흐린건지 좀 가늘게 된 건지 모르겠어요. 암튼 그것 말고는 원하던 제품 하나 더 구입해서 만족해요. 사용할 때는 키스킨 제거하고 보관할 때는 키스킨으로 덮어놓고 있어요.\n",
      "충전용이라 구입할 때 엄청 망설였는데 사용해보고 키감이 넘 좋아서 구입할 수 밖에 없었어요. 그냥 배터리 넣는 거면 오래 사용할 수 있을 것 같은데 주기적으로 충전 신경써야 하는데 백라이트 제거하고 사용하면 몇 달은 신경 안써도 되는 제품이에요.\n",
      "디자인도 키감도 대부분 만족스러운 제품이에요.\n",
      "\n",
      "{\"keyword\": [\"키감\", \"소리\", \"통울림\", \"사용감\", \"키스킨\", \"충전\", \"디자인\"], \"design\": null, \"satisfaction_points\": [\"키감이 진짜 좋고\", \"소리도 타자 치면 약간 보글보글한 소리가 넘 좋아요\", \"통울림도 없고 사용감이 넘 조아서 편해요\", \"디자인도 키감도 대부분 만족스러운 제품이에요\"], \"improvement_areas\": [], \"tone\": \"positive\", \"rating\": 5, \"source\": \"./data/keyboard-review.csv\", \"row\": 1}\n",
      "\n",
      "---------------\n",
      "\n",
      "Position: 3\n",
      "rating: 평점5\n",
      "title: 기존에 게이밍 키보드라 높이가 높아 사무용으로는 적합하지 않았는데 높이가 딱 좋습니다. 손목 통증이 덜하길 바라면서 구매했는데 좋을 것 같아요. 키감도 좋고 소리도 많이 나지 않습\n",
      "review: 기존에 게이밍 키보드라 높이가 높아 사무용으로는 적합하지 않았는데 높이가 딱 좋습니다. 손목 통증이 덜하길 바라면서 구매했는데 좋을 것 같아요. 키감도 좋고 소리도 많이 나지 않습니다. 같이 구매한 스킨을 같이 쓰면 더 조용해지네요. 대신 스킨 사용시 키감이 약간 무겁게 느껴집니다. 디자인 소재 모두 좋아요.\n",
      "\n",
      "{\"keyword\": [\"게이밍 키보드\", \"높이\", \"사무용\", \"손목 통증\", \"키감\", \"소리\", \"스킨\", \"디자인 소재\"], \"design\": null, \"satisfaction_points\": [\"높이가 딱 좋습니다\", \"키감도 좋고 소리도 많이 나지 않습니다\", \"디자인 소재 모두 좋아요\"], \"improvement_areas\": [\"스킨 사용시 키감이 약간 무겁게 느껴집니다\"], \"tone\": \"positive\", \"rating\": 5, \"source\": \"./data/keyboard-review.csv\", \"row\": 2}\n",
      "\n",
      "---------------\n",
      "\n",
      "Position: 4\n",
      "rating: 평점4\n",
      "title: 키보드 자체는 매우 좋습니다. 키감도 확실히 부드럽고 좋아요. 디자인도 비싼만큼 이쁘고 깔끔하구요 무게도 보통의 키보드와 다르게 무겁습니다. 여러 컴터 전환속도도 빠른편이구요. 다\n",
      "review: 키보드 자체는 매우 좋습니다. 키감도 확실히 부드럽고 좋아요. 디자인도 비싼만큼 이쁘고 깔끔하구요 무게도 보통의 키보드와 다르게 무겁습니다. 여러 컴터 전환속도도 빠른편이구요. 다만... 회사에서 쓰려고 7개나 주문했고 거진 100만원을 썼는데 포장상태가 영... 댓글에서 많이 봤듯이 뽁뽁이라도 좀 둘러서 보내주시지 ㅠ 거금을 썼는데도 뽁뽁이 하나 없이 와서 상자 모서리가 찌그러진것도 있고 좀 그렇네요. 포장만 신경써주시면 소비자도 기분좋게 받을거같네요.\n",
      "\n",
      "{\"keyword\": [\"키보드\", \"키감\", \"디자인\", \"무게\", \"전환속도\"], \"design\": null, \"satisfaction_points\": [\"매우 좋습니다\", \"확실히 부드럽고 좋아요\", \"비싼만큼 이쁘고 깔끔하구요\", \"무겁습니다\", \"빠른편이구요\"], \"improvement_areas\": [], \"tone\": \"positive\", \"rating\": 4, \"source\": \"./data/keyboard-review.csv\", \"row\": 3}\n",
      "\n",
      "---------------\n",
      "\n",
      "Position: 5\n",
      "rating: 평점5\n",
      "title: 첫소감은 만족이에요 배송도 하루만에 받았고무게가 적당히 묵직해서 안정감있어요키 눌리는 깊이가 펜타그래프 치고는 깊은것도 제 취향이네요키를 튕기듯이 누르지 않으면 소음도 거의 없는\n",
      "review: 첫소감은 만족이에요 배송도 하루만에 받았고\n",
      "무게가 적당히 묵직해서 안정감있어요\n",
      "키 눌리는 깊이가 펜타그래프 치고는 깊은것도 제 취향이네요\n",
      "키를 튕기듯이 누르지 않으면 소음도 거의 없는 수준이라 사무실에서 쓰기에도 좋고\n",
      "스페이스그레이 컬러도 세련되게 잘뽑힌것 같아요\n",
      "로지텍 옵션 프로그램의 기능은 앞으로 사용하면서 찬찬히 훑어봐야겠어요\n",
      "\n",
      "한가지 아쉬운점은 블루투스로 아이패드에 전환되는 속도가 타사의 3만원짜리 멀티페어링 키보드보다 느린점이에요\n",
      "\n",
      "{\"keyword\": [\"만족\", \"배송\", \"무게\", \"안정감\", \"깊이\", \"소음\", \"수준\", \"좋고\", \"컬러\", \"로지텍\", \"프로그램\", \"기능\", \"아쉬운점\", \"블루투스\", \"아이패드\", \"전환\", \"속도\"], \"design\": null, \"satisfaction_points\": [\"만족\", \"안정감\", \"좋고\"], \"improvement_areas\": [\"블루투스\", \"속도\"], \"tone\": \"positive\", \"rating\": 5, \"source\": \"./data/keyboard-review.csv\", \"row\": 4}\n"
     ]
    }
   ],
   "source": [
    "from typing import Literal, List, Optional\n",
    "\n",
    "import json\n",
    "from pydantic import BaseModel, Field\n",
    "from langchain import hub\n",
    "\n",
    "\n",
    "# 추출할 속성의 내용을 정의\n",
    "class Properties(BaseModel):\n",
    "    # 키워드\n",
    "    keyword: List[str] = Field(description=\"several keywords extracted from review\")\n",
    "    # 디자인\n",
    "    design: Optional[List[str]] = Field(\n",
    "        description=\"several design aspects extracted from review\"\n",
    "    )\n",
    "    # 만족한 부분\n",
    "    satisfaction_points: List[str] = Field(\n",
    "        description=\"the satisfaction points of the product\"\n",
    "    )\n",
    "    # 개선할 부분\n",
    "    improvement_areas: List[str] = Field(\n",
    "        description=\"the improvement areas of the product\"\n",
    "    )\n",
    "    # 평가의 톤: 긍정적 혹은 부정적\n",
    "    tone: Literal[\"positive\", \"negative\"]\n",
    "    # 평점\n",
    "    rating: int = Field(description=\"the rating of the product\")  # 평점\n",
    "\n",
    "\n",
    "document_transformer = create_metadata_tagger(\n",
    "    Properties,  # 추출할 속성\n",
    "    ChatOpenAI(temperature=0, model=\"gpt-3.5-turbo\"),  # OpenAI 모델\n",
    ")\n",
    "\n",
    "# 프롬프트를 불러옵니다.\n",
    "prompt = hub.pull(\"teddynote/metadata-tagger\")\n",
    "\n",
    "# 프롬프트는 생략 가능합니다.\n",
    "# 여기서는 5개의 리뷰만 추출합니다.\n",
    "enhanced_documents = document_transformer.transform_documents(data[:5], prompt=prompt)\n",
    "\n",
    "print(\n",
    "    *[\n",
    "        d.page_content + \"\\n\\n\" + json.dumps(d.metadata, ensure_ascii=False)\n",
    "        for d in enhanced_documents\n",
    "    ],\n",
    "    sep=\"\\n\\n---------------\\n\\n\",\n",
    ")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "py-test",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
